package com.dongnan.hl7v2;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.*;

import java.util.List;

public class MyMessageProcessor {

    public void processorMessage(String messageType, Message message, MyParaMap myParaMap) throws HL7Exception {

        for (MessageTypeAndTableMap messageTypeAndTableMap:myParaMap.messageTypeAndTableMapList){
            if(messageType.equals(messageTypeAndTableMap.messageTypeName)){
                getResultList(message, messageTypeAndTableMap.tableNameAndFieldMap);
            }
        }
    }

    public void getResultList(Structure structurePara, TableNameAndFieldMap tableNameAndFieldMap) throws HL7Exception {

        if (!structurePara.isEmpty()) {
            if (Group.class.isAssignableFrom(structurePara.getClass())) {
                Group group = (Group) structurePara;
                for (String childrenStructName : group.getNames()) {
                    Structure[] structures = group.getAll(childrenStructName);
                    for (Structure structure : structures) {
                        if (!structure.isEmpty()) {
                            getResultList(structure, tableNameAndFieldMap);
                        }
                    }

                }
            } else if (!AbstractGroup.class.isAssignableFrom(structurePara.getClass())) {
                if (Segment.class.isAssignableFrom(structurePara.getClass())) {

                    Segment seg = (Segment) structurePara;
                    String segmentName = seg.getName();

                    if (tableNameAndFieldMap.inSegmentNameSet(segmentName)) {

                        List<String> segmentFieldLlist = tableNameAndFieldMap.segmentNameAndIndexMap.get(segmentName);
                        for (String segmentField : segmentFieldLlist) {
                            if (tableNameAndFieldMap.isInSegmentFieldStack(segmentField)) {
                                tableNameAndFieldMap.updateStackAandResult(segmentField);
                            }
                            int[] index = tableNameAndFieldMap.hl7_index_map.get(segmentField);
                            String hl7FieldValue = getHl7FieldValue(seg, index);
                            tableNameAndFieldMap.setSegmentFieldResult(segmentField, hl7FieldValue);
                        }
                        int l = seg.numFields();
                    }
                }
            }
        }

        if (Message.class.isAssignableFrom(structurePara.getClass())) {
            tableNameAndFieldMap.updateStackAandResult();
        }
    }

    public String getHl7FieldValue(Segment seg, int[] index) throws HL7Exception {

        String value = null;
        int[] subIndex = new int[index.length - 1];
        for (int i = 0; i < subIndex.length; i++) {
            subIndex[i] = index[i + 1];
        }
        Type[] type = seg.getField(index[0]);

        if(null == type || type.length <= 0 ){
            return "";
        }
        value = getTypeValue(type[0], subIndex);
        return value;
    }

    public String getTypeValue(Type type, int[] index) throws HL7Exception {

        String resultValue = null;
        if(index.length == 0){
            resultValue = type.encode().toString();
            return resultValue;
        }
        if (type instanceof Primitive) {
            Primitive primitive = (Primitive) type;
            resultValue = primitive.getValue();
        } else if (type instanceof Composite) {

            Composite composite = (Composite) type;
            Type[] types = composite.getComponents();
            int[] subIndex = new int[index.length - 1];
            for (int i = 0; i < subIndex.length; i++) {
                subIndex[i] = index[i + 1];
            }
            resultValue = getTypeValue(types[index[0] - 1], subIndex);
        }else if(type instanceof Varies){
            Varies varies = (Varies)type;
            try {
                resultValue = varies.encode();
            } catch (HL7Exception e) {
                e.printStackTrace();
            }
        }
        return resultValue;
    }
}
